package br.com.winesys.geta;

import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.PersistenceUnit;
import br.com.winesys.geta.annotations.Selectable;
import br.com.winesys.geta.databinding.component.selector.JPAObjectSelector;
import br.com.winesys.geta.databinding.component.table.TableModel;

final class ObjectSelectorBuilder {

    private ObjectSelectorBuilder() {
    }

    public static <T> JPAObjectSelector<T> createSelector(final Class<T> entityClass) {
        final Selectable selectable = entityClass.getAnnotation(Selectable.class);
        final PersistenceUnit pu = entityClass.getAnnotation(PersistenceUnit.class);
        final NamedQueries queries = entityClass.getAnnotation(NamedQueries.class);
        if (selectable == null) {
            throw new IllegalArgumentException(String.format("Class %s is not marked with @Selectable", entityClass.getSimpleName()));
        }
        if (pu == null) {
            throw new IllegalArgumentException(String.format("Class %s is not marked with @PersistenceUnit", entityClass.getSimpleName()));
        }
        if (queries == null) {
            throw new IllegalArgumentException(String.format("Class %s is not marked with @NamedQueries", entityClass.getSimpleName()));
        }
        NamedQuery listQuery = null;
        NamedQuery loadQuery = null;
        for (NamedQuery query : queries.value()) {
            if (query.name().equalsIgnoreCase(String.format("%s.listSelectable", entityClass.getSimpleName()))) {
                listQuery = query;
            }
            if (query.name().equalsIgnoreCase(String.format("%s.loadSelected", entityClass.getSimpleName()))) {
                loadQuery = query;
            }
        }
        if (listQuery == null) {
            throw new IllegalArgumentException(String.format("Class %s doesn't have @NamedQuery named %s.listSelectable", entityClass.getSimpleName(), entityClass.getSimpleName()));
        }
        if (loadQuery == null) {
            throw new IllegalArgumentException(String.format("Class %s doesn't have @NamedQuery named %s.loadSelected", entityClass.getSimpleName(), entityClass.getSimpleName()));
        }
        final NamedQuery fListQuery = listQuery;
        final NamedQuery fLoadQuery = loadQuery;
        return new JPAObjectSelector<T>() {

            @Override
            protected String getPersistenceUnit() {
                return pu.name();
            }

            @Override
            protected String getListQuery() {
                return fListQuery.query();
            }

            @Override
            protected String getLoadQuery() {
                return fLoadQuery.query();
            }

            @Override
            public String getDisplayProperty() {
                return selectable.display();
            }

            @Override
            public String getKeyProperty() {
                return selectable.key();
            }

            @Override
            public Class<?> getKeyClass() {
                try {
                    return entityClass.getDeclaredField(selectable.key()).getType();
                } catch (Exception ex) {
                    throw new IllegalArgumentException(String.format("Field '%s' not found in class '%s'", selectable.key(), entityClass.getSimpleName()), ex);
                }
            }

            @Override
            public TableModel<T> getTableModel() {
                return TableModelBuilder.createTableModel(entityClass);
            }
        };
    }
}
